library(tidyverse)     # for data cleaning and plotting
library(lubridate)     # for date manipulation
library(openintro)     # for the abbr2state() function
library(ggmap)         # for mapping points on maps
library(gplots)        # for col2hex() function
library(RColorBrewer)  # for color palettes
library(sf)            # for working with spatial data
library(leaflet)       # for highly customizable mapping
library(ggthemes)      # for more themes (including theme_map())
library(plotly)        # for the ggplotly() - basic interactivity
library(gganimate)     # for adding animation layers to ggplots
library(gifski)        # for creating the gif (don't need to load this library every time,but need it installed)
library(transformr)    # for "tweening" (gganimate)
library(shiny)         # for creating interactive apps
library(patchwork)     # for nicely combining ggplot2 graphs  
library(gt)            # for creating nice tables
library(rvest)         # for scraping data
library(robotstxt)     # for checking if you can scrape data
library(dplyr)
library(moderndive)     
library(broom)          
library(equatiomatic)   
library(cowplot)
library(corrplot)
theme_set(theme_minimal())
#For loading our data set
life_expectancy <- read_csv("Life Expectancy Data.csv")

Background and Introduction

As two friends who have recently started going to the gym, one of the key benefits we always read online is that lifting weights adds years to your life. As such, when searching for a data set for this project, the word “Life Expectancy” piqued our interest. After examining some of the determinants which went into it, we decided that this was the ideal data set for us!

Data Collection and Cleaning

We found this data set on Kaggle - a very useful website full of interesting data sets. Here is the link: https://www.kaggle.com/code/shresthakundu/life-expectancy-who

Using data from this data set, we will present multiple visualizations which aim to assess life expectancy differences and changes across countries and years. Moreover, we hope to assess the impacts of certain independent variables such as alcohol consumption and healthcare spending on life expectancy. This will be done by visualizing regressions. (Please note: This is beyond the teachings of this course, but we wanted to seek relationships out of interest, using methods from other Statistics courses.)

Initial Analysis

How is life expectancy distributed when comparing developed countries to underdeveloped ones?

life_expectancy_1 <- life_expectancy %>% 
  select(Country, `Life expectancy`, Year) %>% 
  filter(Country %in% c("Russian Federation", "United Kingdom of Great Britain and Northern Ireland", "Japan", "United States of America",  "Brazil", "Costa Rica", "Australia", "New Zealand", "Indonesia", "Swaziland", "Central African Republic", "Egpyt")) %>% 
  drop_na(Country, `Life expectancy`, Year) %>% 
  group_by(Country, Year)
  life_expectancy_1[life_expectancy_1== "Russian Federation"] <- "Russia"
  life_expectancy_1[life_expectancy_1== "United Kingdom of Great Britain and Northern Ireland"] <- "UK"
  life_expectancy_1[life_expectancy_1== "Central African Republic"] <- "CAR"
  life_expectancy_1[life_expectancy_1== "United States of America"] <- "USA"
  
life_expectancy_1 %>%
  filter(Country %in% c("Russia", "UK", "Japan", "USA", "Mexico", "Brazil", "Argentina", "Peru", "Australia", "New Zealand", "Indonesia", "Swaziland", "CAR", "Egypt")) %>% 
  ggplot(aes(color = Country, x = `Life expectancy`)) +
  labs(title = "Life Expectancies by Country",
       x = "",
       subtitle = "Life Expectancy Distributions Across Selected Countries \n As we can see, Japan has the highest median age, while Central African Republic has the lowest.",
       caption = "By Callum Moir & Gugo Babayan") +
  theme_classic() + 
  theme(plot.title.position = "plot",
        plot.title = element_text(size = 20, face = "bold"),
        plot.subtitle = element_text(size = 10, face = "italic")) +
  geom_boxplot() +
  geom_vline(aes(xintercept = median(`Life expectancy`, na.rm = TRUE)), color = "blue")

Boxplots Showing the distributions and medians across various hand-selected countries.

In this initial graph, we have hand-selected 10 countries from across the world according to personal associations and/or whether or not they are classified as ‘developed’ or ‘developing’ according to the data set. The blue line illustrates the median life expectancy of these countries combined, and shows that 5 of the selected countries fall on either side of this divide. Japan tops the life expectancy, while the Central African Republic (CAR) is at the bottom.

This next plot nicely supports our point that developed countries have much higher average life expectancies than developing ones:

life_expectancy %>% 
  drop_na(`Life expectancy`) %>% 
  ggplot(aes(x=Year,y= `Life expectancy`, color=Status))+
  geom_jitter()+
  geom_smooth(method = "lm", color = "black")+
  transition_states(Status, 
                    transition_length = 2, 
                    state_length = 1) +
  exit_shrink() +
  enter_recolor(color = "lightblue") +
  exit_recolor(color = "lightblue")+
  labs(title = "Average Life Expectancy According to Country Status",
       subtitle = "Status: {closest_state}",
       x = "",
       y = "Life Expectancy")+
theme(legend.position = "none")
anim_save("status_anim.gif")
knitr::include_graphics("status_anim.gif")

This graph shows the differences in life expectancy according to your country’s development status. The red data points represent developed countries, while the blue represents developing countries. The animation makes it clear, through the black regression line, that the average life expectancy for developed countries is much higher than for developing ones.

life_expectancy %>% 
  group_by(Year, Status) %>% 
  summarize(LE_time = sum(`Life expectancy`)) %>% 
  ungroup() %>% 
  complete(Status, Year, 
           fill = list(LE_time = 0)) %>% 
  mutate(variety = fct_reorder(Status, 
                               LE_time, 
                               sum, 
                               .desc = FALSE)) %>% 
  group_by(Status) %>% 
  mutate(cum_LE_time = cumsum(LE_time)) %>% 
  ggplot(aes(x = Year, 
             y = cum_LE_time, 
             fill = Status)) +
  geom_area(position = "stack") +
  geom_text(aes(label = Status),
            position = "stack", 
            check_overlap = TRUE) +
  scale_fill_viridis_d(option = "magma") +
  theme(legend.position = "none") +
  transition_reveal(Year)  +
  labs(title = "Cumulative Life Expectancy",
       subtitle = "Year: {frame_along}",
       x = "",
       y = "")
anim_save("Rate.gif")
knitr::include_graphics("Rate.gif")

This animation takes the cumulative life expectancies from developed and developing countries from 2000-2015. It nicely illustrates that since 2000, the gap between life expectancies in developed countries has increased at a faster rate relative to that of developing countries.

Comparing the Selected Countries With by Examining Changes over Time

These next graphs illustrate how our selected countries differ in life expectancies and rates of improvement over the years.

life_expectancy_1 <- life_expectancy %>% 
  select(Country, `Life expectancy`, Year) %>% 
  filter(Country %in% c("Russian Federation", "United Kingdom of Great Britain and Northern Ireland", "Japan", "United States of America",  "Brazil", "Costa Rica", "Australia", "New Zealand", "Indonesia", "Swaziland", "Central African Republic", "Egpyt")) %>% 
  drop_na(Country, `Life expectancy`, Year) %>% 
  group_by(Country, Year)

  life_expectancy_1[life_expectancy_1== "Russian Federation"] <- "Russia"
  life_expectancy_1[life_expectancy_1== "United Kingdom of Great Britain and Northern Ireland"] <- "UK"
  life_expectancy_1[life_expectancy_1== "Central African Republic"] <- "CAR"
  life_expectancy_1[life_expectancy_1== "United States of America"] <- "USA"

  life_graph<- life_expectancy_1 %>% 
  ggplot(aes(x = Year, y = `Life expectancy`, color = Country)) +
  geom_line() +
    labs(title = "Life Expectancies by Country from 2000 to 2015", subtitle = "Date: 2000 to 2015", x =             element_blank(), y = element_blank())+
    theme(legend.position = "none")+
    facet_wrap("Country", scales = "free_y")+
    theme(
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank())
  ggplotly(life_graph)

The above interactive graph allows you to hover over the years to see what each country’s life expectancy was during that time period. They also show how each country’s life expectancy has grown over time. We see that the USA’s has grown quite constantly, while the UK’s has dipped in more recent years.

life_expectancy_1 <- life_expectancy %>% 
  select(Country, `Life expectancy`, Year) %>% 
  filter(Country %in% c("Russian Federation", "United Kingdom of Great Britain and Northern Ireland", "Japan", "United States of America",  "Brazil", "Costa Rica", "Australia", "New Zealand", "Indonesia", "Swaziland", "Central African Republic", "Egpyt")) %>% 
  drop_na(Country, `Life expectancy`, Year) %>% 
  group_by(Country, Year)

  life_expectancy_1[life_expectancy_1== "Russian Federation"] <- "Russia"
  life_expectancy_1[life_expectancy_1== "United Kingdom of Great Britain and Northern Ireland"] <- "UK"
  life_expectancy_1[life_expectancy_1== "Central African Republic"] <- "CAR"
  life_expectancy_1[life_expectancy_1== "United States of America"] <- "USA"

 life_expectancy_1 %>% 
  ggplot(aes(x = Year, y = `Life expectancy`, color = Country)) +
  geom_line() +
    labs(title = "Life Expectancies by Country from 2000 to 2015", subtitle = "Date: 2000 to 2015", x =             element_blank(), y = element_blank()) +
    transition_reveal(Year)
 anim_save("Test.gif")
knitr::include_graphics("Test.gif")

This graph shows the same trends as the one above, but makes it easier for the viewer to compare these countries’ rates of life expectancy growth over time, and to see how low some are relative to others.

Conclusion and Limitations

The main findings we took from our project are (i) there is a clear distinction between life expectancies in developed vs. developing countries. Developed countries tend to have higher life expectancies, while developing countries tend to have much lower life expectancies. Furthermore, we can see that the life expectancies over time in developed countries is increasing at a much faster rate than that in developing countries. (ii) Increased alcohol consumption tends to decrease life expectancy, while increased government spending on healthcare tends to increase life expectancy.

LS0tCnRpdGxlOiAiSG93IGhhcyBsaWZlIGV4cGVjdGFuY3kgY2hhbmdlZCBvdmVyIHRoZSB5ZWFycyBhbmQgd2hhdCBmYWN0b3JzIGhhdmUgY29udHJpYnV0ZWQgdG8gdGhlc2UgY2hhbmdlcz8iCnN1YnRpdGxlOiAiRGV2ZWxvcGVkIHZzLiBVbmRldmVsb3BlZCBDb3VudHJpZXMiCmF1dGhvcnM6ICJDYWxsdW0gTW9pciAmIEd1Z28gQmFiYXlhbiIKZGF0ZTogIjI5IEFwcmlsIDIwMjIiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGtlZXBfbWQ6IFRSVUUKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZSAKICAgIHRoZW1lOiBjb3NtbwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGVycm9yPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UpCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKSAgICAgIyBmb3IgZGF0YSBjbGVhbmluZyBhbmQgcGxvdHRpbmcKbGlicmFyeShsdWJyaWRhdGUpICAgICAjIGZvciBkYXRlIG1hbmlwdWxhdGlvbgpsaWJyYXJ5KG9wZW5pbnRybykgICAgICMgZm9yIHRoZSBhYmJyMnN0YXRlKCkgZnVuY3Rpb24KbGlicmFyeShnZ21hcCkgICAgICAgICAjIGZvciBtYXBwaW5nIHBvaW50cyBvbiBtYXBzCmxpYnJhcnkoZ3Bsb3RzKSAgICAgICAgIyBmb3IgY29sMmhleCgpIGZ1bmN0aW9uCmxpYnJhcnkoUkNvbG9yQnJld2VyKSAgIyBmb3IgY29sb3IgcGFsZXR0ZXMKbGlicmFyeShzZikgICAgICAgICAgICAjIGZvciB3b3JraW5nIHdpdGggc3BhdGlhbCBkYXRhCmxpYnJhcnkobGVhZmxldCkgICAgICAgIyBmb3IgaGlnaGx5IGN1c3RvbWl6YWJsZSBtYXBwaW5nCmxpYnJhcnkoZ2d0aGVtZXMpICAgICAgIyBmb3IgbW9yZSB0aGVtZXMgKGluY2x1ZGluZyB0aGVtZV9tYXAoKSkKbGlicmFyeShwbG90bHkpICAgICAgICAjIGZvciB0aGUgZ2dwbG90bHkoKSAtIGJhc2ljIGludGVyYWN0aXZpdHkKbGlicmFyeShnZ2FuaW1hdGUpICAgICAjIGZvciBhZGRpbmcgYW5pbWF0aW9uIGxheWVycyB0byBnZ3Bsb3RzCmxpYnJhcnkoZ2lmc2tpKSAgICAgICAgIyBmb3IgY3JlYXRpbmcgdGhlIGdpZiAoZG9uJ3QgbmVlZCB0byBsb2FkIHRoaXMgbGlicmFyeSBldmVyeSB0aW1lLGJ1dCBuZWVkIGl0IGluc3RhbGxlZCkKbGlicmFyeSh0cmFuc2Zvcm1yKSAgICAjIGZvciAidHdlZW5pbmciIChnZ2FuaW1hdGUpCmxpYnJhcnkoc2hpbnkpICAgICAgICAgIyBmb3IgY3JlYXRpbmcgaW50ZXJhY3RpdmUgYXBwcwpsaWJyYXJ5KHBhdGNod29yaykgICAgICMgZm9yIG5pY2VseSBjb21iaW5pbmcgZ2dwbG90MiBncmFwaHMgIApsaWJyYXJ5KGd0KSAgICAgICAgICAgICMgZm9yIGNyZWF0aW5nIG5pY2UgdGFibGVzCmxpYnJhcnkocnZlc3QpICAgICAgICAgIyBmb3Igc2NyYXBpbmcgZGF0YQpsaWJyYXJ5KHJvYm90c3R4dCkgICAgICMgZm9yIGNoZWNraW5nIGlmIHlvdSBjYW4gc2NyYXBlIGRhdGEKbGlicmFyeShkcGx5cikKbGlicmFyeShtb2Rlcm5kaXZlKSAgICAgCmxpYnJhcnkoYnJvb20pICAgICAgICAgIApsaWJyYXJ5KGVxdWF0aW9tYXRpYykgICAKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGNvcnJwbG90KQp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQpgYGAKCgpgYGB7cn0KI0ZvciBsb2FkaW5nIG91ciBkYXRhIHNldApsaWZlX2V4cGVjdGFuY3kgPC0gcmVhZF9jc3YoIkxpZmUgRXhwZWN0YW5jeSBEYXRhLmNzdiIpCmBgYAoKCiMgQmFja2dyb3VuZCBhbmQgSW50cm9kdWN0aW9uCgoKQXMgdHdvIGZyaWVuZHMgd2hvIGhhdmUgcmVjZW50bHkgc3RhcnRlZCBnb2luZyB0byB0aGUgZ3ltLCBvbmUgb2YgdGhlIGtleSBiZW5lZml0cyB3ZSBhbHdheXMgcmVhZCBvbmxpbmUgaXMgdGhhdCBsaWZ0aW5nIHdlaWdodHMgYWRkcyB5ZWFycyB0byB5b3VyIGxpZmUuIEFzIHN1Y2gsIHdoZW4gc2VhcmNoaW5nIGZvciBhIGRhdGEgc2V0IGZvciB0aGlzIHByb2plY3QsIHRoZSB3b3JkICJMaWZlIEV4cGVjdGFuY3kiIHBpcXVlZCBvdXIgaW50ZXJlc3QuIEFmdGVyIGV4YW1pbmluZyBzb21lIG9mIHRoZSBkZXRlcm1pbmFudHMgd2hpY2ggd2VudCBpbnRvIGl0LCB3ZSBkZWNpZGVkIHRoYXQgdGhpcyB3YXMgdGhlIGlkZWFsIGRhdGEgc2V0IGZvciB1cyEKCiMgRGF0YSBDb2xsZWN0aW9uIGFuZCBDbGVhbmluZwoKCldlIGZvdW5kIHRoaXMgZGF0YSBzZXQgb24gS2FnZ2xlIC0gYSB2ZXJ5IHVzZWZ1bCB3ZWJzaXRlIGZ1bGwgb2YgaW50ZXJlc3RpbmcgZGF0YSBzZXRzLiBIZXJlIGlzIHRoZSBsaW5rOiBodHRwczovL3d3dy5rYWdnbGUuY29tL2NvZGUvc2hyZXN0aGFrdW5kdS9saWZlLWV4cGVjdGFuY3ktd2hvCgoKVXNpbmcgZGF0YSBmcm9tIHRoaXMgZGF0YSBzZXQsIHdlIHdpbGwgcHJlc2VudCBtdWx0aXBsZSB2aXN1YWxpemF0aW9ucyB3aGljaCBhaW0gdG8gYXNzZXNzIGxpZmUgZXhwZWN0YW5jeSBkaWZmZXJlbmNlcyBhbmQgY2hhbmdlcyBhY3Jvc3MgY291bnRyaWVzIGFuZCB5ZWFycy4gTW9yZW92ZXIsIHdlIGhvcGUgdG8gYXNzZXNzIHRoZSBpbXBhY3RzIG9mIGNlcnRhaW4gaW5kZXBlbmRlbnQgdmFyaWFibGVzIHN1Y2ggYXMgYWxjb2hvbCBjb25zdW1wdGlvbiBhbmQgaGVhbHRoY2FyZSBzcGVuZGluZyBvbiBsaWZlIGV4cGVjdGFuY3kuIFRoaXMgd2lsbCBiZSBkb25lIGJ5IHZpc3VhbGl6aW5nIHJlZ3Jlc3Npb25zLiAoUGxlYXNlIG5vdGU6IFRoaXMgaXMgYmV5b25kIHRoZSB0ZWFjaGluZ3Mgb2YgdGhpcyBjb3Vyc2UsIGJ1dCB3ZSB3YW50ZWQgdG8gc2VlayByZWxhdGlvbnNoaXBzIG91dCBvZiBpbnRlcmVzdCwgdXNpbmcgbWV0aG9kcyBmcm9tIG90aGVyIFN0YXRpc3RpY3MgY291cnNlcy4pCgoKIyBJbml0aWFsIEFuYWx5c2lzCgoKIyMgSG93IGlzIGxpZmUgZXhwZWN0YW5jeSBkaXN0cmlidXRlZCB3aGVuIGNvbXBhcmluZyBkZXZlbG9wZWQgY291bnRyaWVzIHRvIHVuZGVyZGV2ZWxvcGVkIG9uZXM/CgoKYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmFsdD0gIkJveHBsb3RzIFNob3dpbmcgdGhlIGRpc3RyaWJ1dGlvbnMgYW5kIG1lZGlhbnMgYWNyb3NzIHZhcmlvdXMgaGFuZC1zZWxlY3RlZCBjb3VudHJpZXMuIn0KCmxpZmVfZXhwZWN0YW5jeV8xIDwtIGxpZmVfZXhwZWN0YW5jeSAlPiUgCiAgc2VsZWN0KENvdW50cnksIGBMaWZlIGV4cGVjdGFuY3lgLCBZZWFyKSAlPiUgCiAgZmlsdGVyKENvdW50cnkgJWluJSBjKCJSdXNzaWFuIEZlZGVyYXRpb24iLCAiVW5pdGVkIEtpbmdkb20gb2YgR3JlYXQgQnJpdGFpbiBhbmQgTm9ydGhlcm4gSXJlbGFuZCIsICJKYXBhbiIsICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiLCAgIkJyYXppbCIsICJDb3N0YSBSaWNhIiwgIkF1c3RyYWxpYSIsICJOZXcgWmVhbGFuZCIsICJJbmRvbmVzaWEiLCAiU3dhemlsYW5kIiwgIkNlbnRyYWwgQWZyaWNhbiBSZXB1YmxpYyIsICJFZ3B5dCIpKSAlPiUgCiAgZHJvcF9uYShDb3VudHJ5LCBgTGlmZSBleHBlY3RhbmN5YCwgWWVhcikgJT4lIAogIGdyb3VwX2J5KENvdW50cnksIFllYXIpCiAgbGlmZV9leHBlY3RhbmN5XzFbbGlmZV9leHBlY3RhbmN5XzE9PSAiUnVzc2lhbiBGZWRlcmF0aW9uIl0gPC0gIlJ1c3NpYSIKICBsaWZlX2V4cGVjdGFuY3lfMVtsaWZlX2V4cGVjdGFuY3lfMT09ICJVbml0ZWQgS2luZ2RvbSBvZiBHcmVhdCBCcml0YWluIGFuZCBOb3J0aGVybiBJcmVsYW5kIl0gPC0gIlVLIgogIGxpZmVfZXhwZWN0YW5jeV8xW2xpZmVfZXhwZWN0YW5jeV8xPT0gIkNlbnRyYWwgQWZyaWNhbiBSZXB1YmxpYyJdIDwtICJDQVIiCiAgbGlmZV9leHBlY3RhbmN5XzFbbGlmZV9leHBlY3RhbmN5XzE9PSAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIl0gPC0gIlVTQSIKICAKbGlmZV9leHBlY3RhbmN5XzEgJT4lCiAgZmlsdGVyKENvdW50cnkgJWluJSBjKCJSdXNzaWEiLCAiVUsiLCAiSmFwYW4iLCAiVVNBIiwgIk1leGljbyIsICJCcmF6aWwiLCAiQXJnZW50aW5hIiwgIlBlcnUiLCAiQXVzdHJhbGlhIiwgIk5ldyBaZWFsYW5kIiwgIkluZG9uZXNpYSIsICJTd2F6aWxhbmQiLCAiQ0FSIiwgIkVneXB0IikpICU+JSAKICBnZ3Bsb3QoYWVzKGNvbG9yID0gQ291bnRyeSwgeCA9IGBMaWZlIGV4cGVjdGFuY3lgKSkgKwogIGxhYnModGl0bGUgPSAiTGlmZSBFeHBlY3RhbmNpZXMgYnkgQ291bnRyeSIsCiAgICAgICB4ID0gIiIsCiAgICAgICBzdWJ0aXRsZSA9ICJMaWZlIEV4cGVjdGFuY3kgRGlzdHJpYnV0aW9ucyBBY3Jvc3MgU2VsZWN0ZWQgQ291bnRyaWVzIFxuIEFzIHdlIGNhbiBzZWUsIEphcGFuIGhhcyB0aGUgaGlnaGVzdCBtZWRpYW4gYWdlLCB3aGlsZSBDZW50cmFsIEFmcmljYW4gUmVwdWJsaWMgaGFzIHRoZSBsb3dlc3QuIiwKICAgICAgIGNhcHRpb24gPSAiQnkgQ2FsbHVtIE1vaXIgJiBHdWdvIEJhYmF5YW4iKSArCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2UgPSAiaXRhbGljIikpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbihgTGlmZSBleHBlY3RhbmN5YCwgbmEucm0gPSBUUlVFKSksIGNvbG9yID0gImJsdWUiKQpgYGAKCgpJbiB0aGlzIGluaXRpYWwgZ3JhcGgsIHdlIGhhdmUgaGFuZC1zZWxlY3RlZCAxMCBjb3VudHJpZXMgZnJvbSBhY3Jvc3MgdGhlIHdvcmxkIGFjY29yZGluZyB0byBwZXJzb25hbCBhc3NvY2lhdGlvbnMgYW5kL29yIHdoZXRoZXIgb3Igbm90IHRoZXkgYXJlIGNsYXNzaWZpZWQgYXMgJ2RldmVsb3BlZCcgb3IgJ2RldmVsb3BpbmcnIGFjY29yZGluZyB0byB0aGUgZGF0YSBzZXQuIFRoZSBibHVlIGxpbmUgaWxsdXN0cmF0ZXMgdGhlIG1lZGlhbiBsaWZlIGV4cGVjdGFuY3kgb2YgdGhlc2UgY291bnRyaWVzIGNvbWJpbmVkLCBhbmQgc2hvd3MgdGhhdCA1IG9mIHRoZSBzZWxlY3RlZCBjb3VudHJpZXMgZmFsbCBvbiBlaXRoZXIgc2lkZSBvZiB0aGlzIGRpdmlkZS4gSmFwYW4gdG9wcyB0aGUgbGlmZSBleHBlY3RhbmN5LCB3aGlsZSB0aGUgQ2VudHJhbCBBZnJpY2FuIFJlcHVibGljIChDQVIpIGlzIGF0IHRoZSBib3R0b20uCgoKVGhpcyBuZXh0IHBsb3QgbmljZWx5IHN1cHBvcnRzIG91ciBwb2ludCB0aGF0IGRldmVsb3BlZCBjb3VudHJpZXMgaGF2ZSBtdWNoIGhpZ2hlciBhdmVyYWdlIGxpZmUgZXhwZWN0YW5jaWVzIHRoYW4gZGV2ZWxvcGluZyBvbmVzOgoKCmBgYHtyLCBldmFsPUZBTFNFLGZpZy5oZWlnaHQ9IDQsIGZpZy53aWR0aD04fQpsaWZlX2V4cGVjdGFuY3kgJT4lIAogIGRyb3BfbmEoYExpZmUgZXhwZWN0YW5jeWApICU+JSAKICBnZ3Bsb3QoYWVzKHg9WWVhcix5PSBgTGlmZSBleHBlY3RhbmN5YCwgY29sb3I9U3RhdHVzKSkrCiAgZ2VvbV9qaXR0ZXIoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJibGFjayIpKwogIHRyYW5zaXRpb25fc3RhdGVzKFN0YXR1cywgCiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbl9sZW5ndGggPSAyLCAKICAgICAgICAgICAgICAgICAgICBzdGF0ZV9sZW5ndGggPSAxKSArCiAgZXhpdF9zaHJpbmsoKSArCiAgZW50ZXJfcmVjb2xvcihjb2xvciA9ICJsaWdodGJsdWUiKSArCiAgZXhpdF9yZWNvbG9yKGNvbG9yID0gImxpZ2h0Ymx1ZSIpKwogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBMaWZlIEV4cGVjdGFuY3kgQWNjb3JkaW5nIHRvIENvdW50cnkgU3RhdHVzIiwKICAgICAgIHN1YnRpdGxlID0gIlN0YXR1czoge2Nsb3Nlc3Rfc3RhdGV9IiwKICAgICAgIHggPSAiIiwKICAgICAgIHkgPSAiTGlmZSBFeHBlY3RhbmN5IikrCnRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYW5pbV9zYXZlKCJzdGF0dXNfYW5pbS5naWYiKQpgYGAKCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoInN0YXR1c19hbmltLmdpZiIpCmBgYAoKClRoaXMgZ3JhcGggc2hvd3MgdGhlIGRpZmZlcmVuY2VzIGluIGxpZmUgZXhwZWN0YW5jeSBhY2NvcmRpbmcgdG8geW91ciBjb3VudHJ5J3MgZGV2ZWxvcG1lbnQgc3RhdHVzLiBUaGUgcmVkIGRhdGEgcG9pbnRzIHJlcHJlc2VudCBkZXZlbG9wZWQgY291bnRyaWVzLCB3aGlsZSB0aGUgYmx1ZSByZXByZXNlbnRzIGRldmVsb3BpbmcgY291bnRyaWVzLiBUaGUgYW5pbWF0aW9uIG1ha2VzIGl0IGNsZWFyLCB0aHJvdWdoIHRoZSBibGFjayByZWdyZXNzaW9uIGxpbmUsIHRoYXQgdGhlIGF2ZXJhZ2UgbGlmZSBleHBlY3RhbmN5IGZvciBkZXZlbG9wZWQgY291bnRyaWVzIGlzIG11Y2ggaGlnaGVyIHRoYW4gZm9yIGRldmVsb3Bpbmcgb25lcy4KCgpgYGB7ciwgZXZhbD0gRkFMU0V9CmxpZmVfZXhwZWN0YW5jeSAlPiUgCiAgZ3JvdXBfYnkoWWVhciwgU3RhdHVzKSAlPiUgCiAgc3VtbWFyaXplKExFX3RpbWUgPSBzdW0oYExpZmUgZXhwZWN0YW5jeWApKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBjb21wbGV0ZShTdGF0dXMsIFllYXIsIAogICAgICAgICAgIGZpbGwgPSBsaXN0KExFX3RpbWUgPSAwKSkgJT4lIAogIG11dGF0ZSh2YXJpZXR5ID0gZmN0X3Jlb3JkZXIoU3RhdHVzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExFX3RpbWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZXNjID0gRkFMU0UpKSAlPiUgCiAgZ3JvdXBfYnkoU3RhdHVzKSAlPiUgCiAgbXV0YXRlKGN1bV9MRV90aW1lID0gY3Vtc3VtKExFX3RpbWUpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgCiAgICAgICAgICAgICB5ID0gY3VtX0xFX3RpbWUsIAogICAgICAgICAgICAgZmlsbCA9IFN0YXR1cykpICsKICBnZW9tX2FyZWEocG9zaXRpb24gPSAic3RhY2siKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFN0YXR1cyksCiAgICAgICAgICAgIHBvc2l0aW9uID0gInN0YWNrIiwgCiAgICAgICAgICAgIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIm1hZ21hIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHRyYW5zaXRpb25fcmV2ZWFsKFllYXIpICArCiAgbGFicyh0aXRsZSA9ICJDdW11bGF0aXZlIExpZmUgRXhwZWN0YW5jeSIsCiAgICAgICBzdWJ0aXRsZSA9ICJZZWFyOiB7ZnJhbWVfYWxvbmd9IiwKICAgICAgIHggPSAiIiwKICAgICAgIHkgPSAiIikKYW5pbV9zYXZlKCJSYXRlLmdpZiIpCmBgYApgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIlJhdGUuZ2lmIikKYGBgCgoKVGhpcyBhbmltYXRpb24gdGFrZXMgdGhlIGN1bXVsYXRpdmUgbGlmZSBleHBlY3RhbmNpZXMgZnJvbSBkZXZlbG9wZWQgYW5kIGRldmVsb3BpbmcgY291bnRyaWVzIGZyb20gMjAwMC0yMDE1LiBJdCBuaWNlbHkgaWxsdXN0cmF0ZXMgdGhhdCBzaW5jZSAyMDAwLCB0aGUgZ2FwIGJldHdlZW4gbGlmZSBleHBlY3RhbmNpZXMgaW4gZGV2ZWxvcGVkIGNvdW50cmllcyBoYXMgaW5jcmVhc2VkIGF0IGEgZmFzdGVyIHJhdGUgcmVsYXRpdmUgdG8gdGhhdCBvZiBkZXZlbG9waW5nIGNvdW50cmllcy4KCgojIyBDb21wYXJpbmcgdGhlIFNlbGVjdGVkIENvdW50cmllcyBXaXRoIGJ5IEV4YW1pbmluZyBDaGFuZ2VzIG92ZXIgVGltZQoKClRoZXNlIG5leHQgZ3JhcGhzIGlsbHVzdHJhdGUgaG93IG91ciBzZWxlY3RlZCBjb3VudHJpZXMgZGlmZmVyIGluIGxpZmUgZXhwZWN0YW5jaWVzIGFuZCByYXRlcyBvZiBpbXByb3ZlbWVudCBvdmVyIHRoZSB5ZWFycy4KCgpgYGB7ciwgZmlnLndpZHRoPTE4LCBmaWcuaGVpZ2h0PTEyfQpsaWZlX2V4cGVjdGFuY3lfMSA8LSBsaWZlX2V4cGVjdGFuY3kgJT4lIAogIHNlbGVjdChDb3VudHJ5LCBgTGlmZSBleHBlY3RhbmN5YCwgWWVhcikgJT4lIAogIGZpbHRlcihDb3VudHJ5ICVpbiUgYygiUnVzc2lhbiBGZWRlcmF0aW9uIiwgIlVuaXRlZCBLaW5nZG9tIG9mIEdyZWF0IEJyaXRhaW4gYW5kIE5vcnRoZXJuIElyZWxhbmQiLCAiSmFwYW4iLCAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiwgICJCcmF6aWwiLCAiQ29zdGEgUmljYSIsICJBdXN0cmFsaWEiLCAiTmV3IFplYWxhbmQiLCAiSW5kb25lc2lhIiwgIlN3YXppbGFuZCIsICJDZW50cmFsIEFmcmljYW4gUmVwdWJsaWMiLCAiRWdweXQiKSkgJT4lIAogIGRyb3BfbmEoQ291bnRyeSwgYExpZmUgZXhwZWN0YW5jeWAsIFllYXIpICU+JSAKICBncm91cF9ieShDb3VudHJ5LCBZZWFyKQoKICBsaWZlX2V4cGVjdGFuY3lfMVtsaWZlX2V4cGVjdGFuY3lfMT09ICJSdXNzaWFuIEZlZGVyYXRpb24iXSA8LSAiUnVzc2lhIgogIGxpZmVfZXhwZWN0YW5jeV8xW2xpZmVfZXhwZWN0YW5jeV8xPT0gIlVuaXRlZCBLaW5nZG9tIG9mIEdyZWF0IEJyaXRhaW4gYW5kIE5vcnRoZXJuIElyZWxhbmQiXSA8LSAiVUsiCiAgbGlmZV9leHBlY3RhbmN5XzFbbGlmZV9leHBlY3RhbmN5XzE9PSAiQ2VudHJhbCBBZnJpY2FuIFJlcHVibGljIl0gPC0gIkNBUiIKICBsaWZlX2V4cGVjdGFuY3lfMVtsaWZlX2V4cGVjdGFuY3lfMT09ICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiXSA8LSAiVVNBIgoKICBsaWZlX2dyYXBoPC0gbGlmZV9leHBlY3RhbmN5XzEgJT4lIAogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBgTGlmZSBleHBlY3RhbmN5YCwgY29sb3IgPSBDb3VudHJ5KSkgKwogIGdlb21fbGluZSgpICsKICAgIGxhYnModGl0bGUgPSAiTGlmZSBFeHBlY3RhbmNpZXMgYnkgQ291bnRyeSBmcm9tIDIwMDAgdG8gMjAxNSIsIHN1YnRpdGxlID0gIkRhdGU6IDIwMDAgdG8gMjAxNSIsIHggPSAgICAgICAgICAgICBlbGVtZW50X2JsYW5rKCksIHkgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsKICAgIGZhY2V0X3dyYXAoIkNvdW50cnkiLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgICB0aGVtZSgKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKQogIGdncGxvdGx5KGxpZmVfZ3JhcGgpCmBgYAoKClRoZSBhYm92ZSBpbnRlcmFjdGl2ZSBncmFwaCBhbGxvd3MgeW91IHRvIGhvdmVyIG92ZXIgdGhlIHllYXJzIHRvIHNlZSB3aGF0IGVhY2ggY291bnRyeSdzIGxpZmUgZXhwZWN0YW5jeSB3YXMgZHVyaW5nIHRoYXQgdGltZSBwZXJpb2QuIFRoZXkgYWxzbyBzaG93IGhvdyBlYWNoIGNvdW50cnkncyBsaWZlIGV4cGVjdGFuY3kgaGFzIGdyb3duIG92ZXIgdGltZS4gV2Ugc2VlIHRoYXQgdGhlIFVTQSdzIGhhcyBncm93biBxdWl0ZSBjb25zdGFudGx5LCB3aGlsZSB0aGUgVUsncyBoYXMgZGlwcGVkIGluIG1vcmUgcmVjZW50IHllYXJzLgoKCgpgYGB7ciwgZmlnLndpZHRoPTE4LCBmaWcuaGVpZ2h0PTEyLCBldmFsID0gRkFMU0V9CmxpZmVfZXhwZWN0YW5jeV8xIDwtIGxpZmVfZXhwZWN0YW5jeSAlPiUgCiAgc2VsZWN0KENvdW50cnksIGBMaWZlIGV4cGVjdGFuY3lgLCBZZWFyKSAlPiUgCiAgZmlsdGVyKENvdW50cnkgJWluJSBjKCJSdXNzaWFuIEZlZGVyYXRpb24iLCAiVW5pdGVkIEtpbmdkb20gb2YgR3JlYXQgQnJpdGFpbiBhbmQgTm9ydGhlcm4gSXJlbGFuZCIsICJKYXBhbiIsICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiLCAgIkJyYXppbCIsICJDb3N0YSBSaWNhIiwgIkF1c3RyYWxpYSIsICJOZXcgWmVhbGFuZCIsICJJbmRvbmVzaWEiLCAiU3dhemlsYW5kIiwgIkNlbnRyYWwgQWZyaWNhbiBSZXB1YmxpYyIsICJFZ3B5dCIpKSAlPiUgCiAgZHJvcF9uYShDb3VudHJ5LCBgTGlmZSBleHBlY3RhbmN5YCwgWWVhcikgJT4lIAogIGdyb3VwX2J5KENvdW50cnksIFllYXIpCgogIGxpZmVfZXhwZWN0YW5jeV8xW2xpZmVfZXhwZWN0YW5jeV8xPT0gIlJ1c3NpYW4gRmVkZXJhdGlvbiJdIDwtICJSdXNzaWEiCiAgbGlmZV9leHBlY3RhbmN5XzFbbGlmZV9leHBlY3RhbmN5XzE9PSAiVW5pdGVkIEtpbmdkb20gb2YgR3JlYXQgQnJpdGFpbiBhbmQgTm9ydGhlcm4gSXJlbGFuZCJdIDwtICJVSyIKICBsaWZlX2V4cGVjdGFuY3lfMVtsaWZlX2V4cGVjdGFuY3lfMT09ICJDZW50cmFsIEFmcmljYW4gUmVwdWJsaWMiXSA8LSAiQ0FSIgogIGxpZmVfZXhwZWN0YW5jeV8xW2xpZmVfZXhwZWN0YW5jeV8xPT0gIlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSJdIDwtICJVU0EiCgogbGlmZV9leHBlY3RhbmN5XzEgJT4lIAogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBgTGlmZSBleHBlY3RhbmN5YCwgY29sb3IgPSBDb3VudHJ5KSkgKwogIGdlb21fbGluZSgpICsKICAgIGxhYnModGl0bGUgPSAiTGlmZSBFeHBlY3RhbmNpZXMgYnkgQ291bnRyeSBmcm9tIDIwMDAgdG8gMjAxNSIsIHN1YnRpdGxlID0gIkRhdGU6IDIwMDAgdG8gMjAxNSIsIHggPSAgICAgICAgICAgICBlbGVtZW50X2JsYW5rKCksIHkgPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIHRyYW5zaXRpb25fcmV2ZWFsKFllYXIpCiBhbmltX3NhdmUoIlRlc3QuZ2lmIikKYGBgCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiVGVzdC5naWYiKQpgYGAKCgpUaGlzIGdyYXBoIHNob3dzIHRoZSBzYW1lIHRyZW5kcyBhcyB0aGUgb25lIGFib3ZlLCBidXQgbWFrZXMgaXQgZWFzaWVyIGZvciB0aGUgdmlld2VyIHRvIGNvbXBhcmUgdGhlc2UgY291bnRyaWVzJyByYXRlcyBvZiBsaWZlIGV4cGVjdGFuY3kgZ3Jvd3RoIG92ZXIgdGltZSwgYW5kIHRvIHNlZSBob3cgbG93IHNvbWUgYXJlIHJlbGF0aXZlIHRvIG90aGVycy4KCgojIyBVc2luZyBSZWdyZXNzaW9ucyB0byBEZXRlcm1pbmUgVHJlbmRzIG9mIG90aGVyIFZhcmlhYmxlcwoKCmBgYHtyLCBmaWcud2lkdGg9NX0KcGxvdDEgPC0gbGlmZV9leHBlY3RhbmN5ICU+JQogIGZpbHRlcihDb3VudHJ5ICVpbiUgYygiUnVzc2lhbiBGZWRlcmF0aW9uIiwgIlVuaXRlZCBLaW5nZG9tIG9mIEdyZWF0IEJyaXRhaW4gYW5kIE5vcnRoZXJuIElyZWxhbmQiLCAiSmFwYW4iLCAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiwgICJCcmF6aWwiLCAiQXVzdHJhbGlhIiwgIk5ldyBaZWFsYW5kIikpICU+JQogIGdyb3VwX2J5KENvdW50cnkpICU+JSAKICBkcm9wX25hKEFsY29ob2wpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBBbGNvaG9sLCB5ID0gYExpZmUgZXhwZWN0YW5jeWApKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIGxhYnMoeCA9ICJBbGNvaG9sIENvbnN1bXB0aW9uIChQZXJjZW50YWdlIG9mIFBvcHVsYXRpb24pIiwgeSA9ICJMaWZlIEV4cGVjdGFuY3kiKQoKcGxvdDIgPC0gbGlmZV9leHBlY3RhbmN5ICU+JQogIGZpbHRlcihDb3VudHJ5ICVpbiUgYygiUnVzc2lhbiBGZWRlcmF0aW9uIiwgIlVuaXRlZCBLaW5nZG9tIG9mIEdyZWF0IEJyaXRhaW4gYW5kIE5vcnRoZXJuIElyZWxhbmQiLCAiSmFwYW4iLCAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiwgICJCcmF6aWwiLCAiQXVzdHJhbGlhIiwgIk5ldyBaZWFsYW5kIikpICU+JQogIGdyb3VwX2J5KENvdW50cnkpICU+JSAKICBkcm9wX25hKGBUb3RhbCBleHBlbmRpdHVyZWApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBgVG90YWwgZXhwZW5kaXR1cmVgLCB5ID0gYExpZmUgZXhwZWN0YW5jeWApKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIGxhYnMoeCA9ICJQZXJjZW50YWdlIG9mIEdvdmVybm1lbnQgU3BlbmRpbmcgb24gSGVhbHRoY2FyZSIsIHkgPSAiTGlmZSBFeHBlY3RhbmN5IikKCnBsb3RfZ3JpZChwbG90MSwgcGxvdDIsIGxhYmVscyA9ICJBVVRPIikKYGBgCgoKVG8gZXhwYW5kIG9uIG91ciBmaW5kaW5ncywgd2UgZGVjaWRlZCB0byBjb25kdWN0IG91ciBvd24gcmVzZWFyY2ggaW50byByZWdyZXNzaW9ucyBhbmQgY29ycmVsYXRpb25zIGluIG9yZGVyIHRvIGRldGVybWluZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gY2VydGFpbiB2YXJpYWJsZXMgYW5kIGxpZmUgZXhwZWN0YW5jaWVzLiBJbiB0aGUgYWJvdmUgZ3JhcGgsIHdlIGNhbiBzZWUgdGhhdCBvbiBhdmVyYWdlLCBhY3Jvc3Mgb3VyIHNlbGVjdGVkIGNvdW50cmllcywgdGhlcmUgaXMgYSBzdHJvbmcgbmVnYXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBhbGNvaG9sIGNvbnN1bXB0aW9uIGFuZCBsaWZlIGV4cGVjdGFuY3kuIFRoYXQgaXMsIGFzIGFsY29ob2wgY29uc3VtcHRpb24gaW5jcmVhc2VzLCBsaWZlIGV4cGVjdGFuY3kgdGVuZHMgdG8gZmFsbC4gClRoZSBncmFwaCBuZXh0IHRvIGl0IHNob3dzIGEgc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHBlcmNlbnRhZ2Ugb2YgZ292ZXJubWVudCBzcGVuZGluZyBvbiBoZWFsdGhjYXJlIGFuZCBsaWZlIGV4cGVjdGFuY3kuIFRoYXQgaXMsIGFzIHRoZSBnb3Zlcm5tZW50cyBhY3Jvc3MgdGhlc2UgY291bnRyaWVzIHNwZW5kcyBhIGhpZ2hlciBwZXJjZW50YWdlIG9mIHRoZWlyIGJ1ZGdldCBvbiBpbXByb3ZpbmcgaGVhbHRoY2FyZSwgbGlmZSBleHBlY3RhbmN5IHRlbmRzIHRpbyBpbmNyZWFzZS4KCgoKYGBge3IsIGZpZy5hbGlnbj0nbGVmdCcsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMn0KY29ycmVsYXRpb24xPC0gbGlmZV9leHBlY3RhbmN5ICU+JSAKICBmaWx0ZXIoU3RhdHVzPT0iRGV2ZWxvcGVkIikgJT4lCiAgc2VsZWN0KC1ZZWFyLCAtQ291bnRyeSwgLVN0YXR1cykgJT4lIAogIGRyb3BfbmEoKQpjb3JyZWxhdGlvbl9hbmltPC0KY29ycnBsb3QoY29yKGNvcnJlbGF0aW9uMSksdHlwZT0idXBwZXIiLG1ldGhvZD0iY2lyY2xlIix0aXRsZT0iQ29ycmVsYXRpb24gcGxvdCBiZXR3ZWVuIHZhcmlhYmxlcyIsbWFyPWMoMC4xLDAuMSwwLjEsMC4xKSwgaW5zaWc9ImJsYW5rIiwgbmEubGFiZWwgPSAiICIpCmBgYAoKYGBge3IsIGZpZy5hbGlnbj0nbGVmdCcsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMn0KY29ycmVsYXRpb24yPC0gbGlmZV9leHBlY3RhbmN5ICU+JSAKICBmaWx0ZXIoU3RhdHVzPT0iRGV2ZWxvcGluZyIpICU+JQogIHNlbGVjdCgtWWVhciwgLUNvdW50cnksIC1TdGF0dXMpICU+JSAKICBkcm9wX25hKCkKY29ycmVsYXRpb25fYW5pbTwtCmNvcnJwbG90KGNvcihjb3JyZWxhdGlvbjIpLHR5cGU9InVwcGVyIixtZXRob2Q9ImNpcmNsZSIsdGl0bGU9IkNvcnJlbGF0aW9uIHBsb3QgYmV0d2VlbiB2YXJpYWJsZXMiLG1hcj1jKDAuMSwwLjEsMC4xLDAuMSksIGluc2lnPSJibGFuayIpCmBgYAoKCiMjIENvbmNsdXNpb24gYW5kIExpbWl0YXRpb25zCgoKVGhlIG1haW4gZmluZGluZ3Mgd2UgdG9vayBmcm9tIG91ciBwcm9qZWN0IGFyZSAoaSkgdGhlcmUgaXMgYSBjbGVhciBkaXN0aW5jdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jaWVzIGluIGRldmVsb3BlZCB2cy4gZGV2ZWxvcGluZyBjb3VudHJpZXMuIERldmVsb3BlZCBjb3VudHJpZXMgdGVuZCB0byBoYXZlIGhpZ2hlciBsaWZlIGV4cGVjdGFuY2llcywgd2hpbGUgZGV2ZWxvcGluZyBjb3VudHJpZXMgdGVuZCB0byBoYXZlIG11Y2ggbG93ZXIgbGlmZSBleHBlY3RhbmNpZXMuIEZ1cnRoZXJtb3JlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGxpZmUgZXhwZWN0YW5jaWVzIG92ZXIgdGltZSBpbiBkZXZlbG9wZWQgY291bnRyaWVzIGlzIGluY3JlYXNpbmcgYXQgYSBtdWNoIGZhc3RlciByYXRlIHRoYW4gdGhhdCBpbiBkZXZlbG9waW5nIGNvdW50cmllcy4gKGlpKSBJbmNyZWFzZWQgYWxjb2hvbCBjb25zdW1wdGlvbiB0ZW5kcyB0byBkZWNyZWFzZSBsaWZlIGV4cGVjdGFuY3ksIHdoaWxlIGluY3JlYXNlZCBnb3Zlcm5tZW50IHNwZW5kaW5nIG9uIGhlYWx0aGNhcmUgdGVuZHMgdG8gaW5jcmVhc2UgbGlmZSBleHBlY3RhbmN5LgoKCgo=